 #include <ESP8266WiFi.h>
WiFiClient client;
char sid[20],psw[30];//这里是我的wifi，你使用时修改为你要连接的wifi ssid
char flag_initial=2,flag_connect=0;//该标志位表示是否处于WIFI账号密码获取阶段，
char RecDate_buff[300],RecDate_buff_index=0;//缓存的数据，其中RecDate_buff_index表示数组顶指针
void mencopy(char* dateFrom,char* dateTo,uint16_t dateFromStart,uint16_t dateToStart,uint16_t lenth);
void mendec(char* date,uint16_t decLenth,uint16_t lenth);
uint16_t processdate(char recDate[],uint16_t len);
void setup()
{
    pinMode(2, OUTPUT);
    digitalWrite(2, HIGH);
    Serial.begin(115200);
    delay(10);
    //把初始数据读取完
    if (Serial.available()){delay(10);size_t counti = Serial.available();if(counti>1){uint8_t sbuf[counti];Serial.readBytes(sbuf, counti);}}
    digitalWrite(2, LOW);
    while(true)//循环获取到wifi的ssid和password为止
    {
      if (Serial.available())
      {
        delay(10);
        size_t counti = Serial.available();
        if(counti>1)
        {
          uint8_t sbuf[counti],dec_index;
          Serial.readBytes(sbuf, counti);
          mencopy((char*)sbuf,RecDate_buff,0,RecDate_buff_index,counti);//把接收到的数据增加到数组后
          RecDate_buff_index+=counti;//改变数组顶指针
          while(dec_index=processdate(RecDate_buff,RecDate_buff_index))//处理数据,返回值表示应该缩减的数据长度
          {
            mendec(RecDate_buff,dec_index,300);//处理完数据后，缓存缩减
            RecDate_buff_index-=dec_index;
          }
          if(!flag_initial)break;
        }
      }
    }
    Serial.print("Connecting to ");//写几句提示，哈哈
    WiFi.begin((char *)sid, (char *)psw);
    Serial.print("ssid:");Serial.println((char *)sid);Serial.print("psw:");Serial.println((char *)psw);
    while (WiFi.status() != WL_CONNECTED)//WiFi.status() ，这个函数是wifi连接状态，返回wifi链接状态
                                         //这里就不一一赘述它返回的数据了，有兴趣的到ESP8266WiFi.cpp中查看
    {
        delay(500);
        Serial.print(".");
    }//如果没有连通向串口发送.....
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址

    //开始通讯前，先清除所有收到的数据
}
  
void loop()
{
    digitalWrite(2, HIGH);
    while (!client.connected())//几个非连接的异常处理
    {
        flag_connect=0;
        if (!client.connect("lhqiot.top",5050))
        {
          //client.stop();
          delay(200);
          if (Serial.available())//串口读取到的转发到wifi，因为串口是一位一位的发送所以在这里缓存完再发送
          {
          delay(10);
          size_t counti = Serial.available();
          if(counti>1)
          {
            uint8_t sbuf[counti],dec_index;
            Serial.readBytes(sbuf, counti);
            mencopy((char*)sbuf,RecDate_buff,0,RecDate_buff_index,counti);//把接收到的数据增加到数组后
            RecDate_buff_index+=counti;//改变数组顶指针
            processdate(RecDate_buff,RecDate_buff_index);
          }
        }
        }
        
    }
    flag_connect=1;
    while (client.available())//改动的就这里啦，无线读取到的数据转发到到串口
    {
        uint8_t c = client.read();
        Serial.write(c);
    }


    if (Serial.available())//串口读取到的转发到wifi，因为串口是一位一位的发送所以在这里缓存完再发送
    {
        delay(10);
        size_t counti = Serial.available();
        if(counti>1)
        {
          uint8_t sbuf[counti],dec_index;
          Serial.readBytes(sbuf, counti);
          mencopy((char*)sbuf,RecDate_buff,0,RecDate_buff_index,counti);//把接收到的数据增加到数组后
          RecDate_buff_index+=counti;//改变数组顶指针
          while(dec_index=processdate(RecDate_buff,RecDate_buff_index))//处理数据,返回值表示应该缩减的数据长度
          {
            mendec(RecDate_buff,dec_index,300);//处理完数据后，缓存缩减
            RecDate_buff_index-=dec_index;
          }
        }
    }
}
//此处规定通讯协议，每次数据以E,F结尾，通过MCU向ESP8266发送SSID和password。首先接收SSID，然后接收password
//如果监测到一整串的数据，那么执行操作,实现递归后将会把所有数据读出，并返回截取的总长度，若未监测到数据则返回0
uint16_t processdate(char recDate[],uint16_t len)
{
  uint16_t  i=0,j=0,stop_index;
  for(i=0;i<len;i++)
  {
    if(recDate[i]=='F')
      {
        if(recDate[i-1]=='E')
        {
          stop_index=i+1;
          if(flag_initial)//表示此处接收WIFI信息
          {
            flag_initial--;
            if(flag_initial==1){mencopy(recDate,sid,0,0,stop_index-2);}else{mencopy(recDate,psw,0,0,stop_index-2);}
            ////////////////////////////////////////////////
          }
          else //透传部分程序
          {
            if((stop_index==3)&&(recDate[i-2]=='C'))//查询任务
            {
              if(flag_connect)
              {Serial.print("OEF");}//发送连接成功的信号
              else{Serial.print("QEF");mendec(RecDate_buff,RecDate_buff_index,300);RecDate_buff_index=0;return 0;}//发送未连接成功的信号,并去掉所有数据
            }
            else //透传
            {
              if(flag_connect)//连接状态，可以正常收发
              {client.write((uint8_t*)recDate,stop_index-2);}
              else //未连接服务器，发送未连接状态
              {Serial.print("QEF");mendec(RecDate_buff,RecDate_buff_index,300);RecDate_buff_index=0;return 0;}//将接收到的所有数据丢弃，并返回未查找到数据
              //Serial.write((uint8_t*)recDate,stop_index);//从本数据开始到某个短句结尾
            }
          }
          return stop_index;
        }
      }
  }
  return 0;
}
//该函数实现两个数组的复制
void mencopy(char* dateFrom,char* dateTo,uint16_t dateFromStart,uint16_t dateToStart,uint16_t lenth)
{
  uint16_t i=0;
  for(i=0;i<lenth;i++)
  {
    dateTo[dateToStart+i]=dateFrom[dateFromStart+i];
  }
}
//该函数实现数组的前decLenth长度去除,lenth表示数组总长度
void mendec(char* date,uint16_t decLenth,uint16_t lenth)
{
  uint16_t i=decLenth;
  for(i=decLenth;i<lenth;i++)
  {
    date[i-decLenth]=date[i];
  }
}
